"""
作用：对selenium进行二次封装，供怕个包中的类继承
类名：Base
方法：
    __init__:创建webdriver对象
    get:请求目标网址
    find_element:单个元素定位
    find_elements:多个元素定位
    send_keys:输入内容
    click:点击
    text:获取标签文本

    quit:退出浏览器
"""
from time import sleep
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import InvalidArgumentException, WebDriverException, TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait


# 打开浏览器驱动,返回webdriver对象
def get_driver(browser='chrome'):
    if browser == 'chrome':
        return webdriver.Chrome()
    else:
        return webdriver.Firefox()


class Base:

    def __init__(self,driver):
        """
        # 初始化webdriver对象
        """
        self.driver = driver
        sleep(1)


    def get(self, url):
        """
        # 封装访问方法
        :param url:
        :return:
        """
        try:
            self.driver.get(url)
            self.driver.implicitly_wait(4)
        except (InvalidArgumentException, WebDriverException) as e:
            print(e)


    def find_element(self,locator,timeout=5,poll_frequency=0.5):
        """
        # 封装定位单个元素方法
        :param locator:
        :param timeout:
        :param poll_frequency:
        :return:
        """
        try:
            return WebDriverWait(self.driver,timeout,poll_frequency).until(EC.presence_of_element_located(locator),message='单个元素定位错误')
        except (InvalidArgumentException, WebDriverException) as e:
            print(e)

    def find_elements(self,locator,timeout=5,poll_frequency=0.5):
        """
        封装定位多个元素的方法
        :param locator:
        :param timeout:
        :param poll_frequency:
        :return:
        """
        try:
            return WebDriverWait(self.driver,timeout,poll_frequency).until(EC.presence_of_all_elements_located(locator),message='多个元素定位错误')
        except (InvalidArgumentException,WebDriverException) as e:
            print(e)

    def send_keys(self,locator,content):
        """
        封装输入内容方法
        :param locator:
        :param content:
        :return:
        """
        sk_webelement = self.find_element(locator)
        if sk_webelement:
            return sk_webelement.send_keys(content)

    def click(self,locator):
        """
        封装click方法
        :param locator:
        :return:
        """
        cl_webelement =self.find_element(locator)
        if cl_webelement:
            return cl_webelement.click()

    def text(self,locator):
        """
        封装获取标签文本方法
        :param locator:
        :return:
        """
        text_element = self.find_element(locator)
        if text_element:
            return text_element.text

    def attribute(self,locator,attribute):

        target_element = self.find_element(locator)
        if target_element:
            return target_element.get_attribute(attribute)

    def switch_to_frame(self,locator):
        """
        封装切换frame的方法
        :param locator:
        :return:
        """
        frame_element = self.find_element(locator)
        return self.driver.switch_to.frame(frame_element)

    def switch_to_default_frame(self):
        """
        封装返回第一级frame的方法
        :return:
        """
        return self.driver.switch_to.default_content()

    def switch_to_window(self,i):
        """
        封装切换window的方法
        :param i: 0为第一次get打开的页面，1为第二次get打开的页面
        :return:
        """
        handles_list = self.driver.window_handles()
        return self.driver.switch_to.window(handles_list[i])

    def refresh(self):
        return self.driver.refresh()

    def forward(self):
        return self.driver.forward()

    def back(self):
        return self.driver.back()

    def delete_content(self,locator):
        """
        删除文本内容
        :return:
        """
        text_element = self.find_element(locator)
        text_element.send_keys(Keys.CONTROL,'a')
        text_element.send_keys(Keys.BACKSPACE)

    def alert_accept(self):
        # 系统弹窗处理，确定
        alert = self.driver.switch_to.alert
        alert.accept()

    def alert_dismiss(self):
        # 系统弹窗处理，取消
        alert = self.driver.switch_to.alert
        alert.dismiss()

    def select(self,locator,value):
        """
        通过value值选择下拉框中options选项
        :param locator: select元素定位
        :param value: options的value属性
        :return:
        """
        select_element = self.find_element(locator)
        select = Select(select_element)
        select.select_by_value(value)

    def radio(self,locator):
        """
        单选框选择
        :param locator:
        :return:
        """
        radio_element = self.find_element(locator)
        radio_element.click()

    def checkbox(self,locator,index):
        """
        定位checkbox元素列表，传入选项索引，单选checkbox中的选项
        :param locator: 定位checkbox元素，返回列表
        :param index: 选项在checkbox_elements中的索引
        :return:
        """
        checkbox_elements = self.find_elements(locator)
        checkbox_elements[index].click()

    def scroll_to_browse_tail(self):
        """
        封装平滑移动到页面底部的方法
        :return:
        """
        js = 'window.scrollTo({top:document.body.scrollHeight, left:0, behavior:"smooth"})'
        self.driver.execute_script(js)

    def scroll_to_element(self,locator):
        """
        封装移动到目标webelement的方法
        :param locator:
        :return:
        """
        self.driver.execute_script('argument[0].scrollIntoView()',locator)

    def login_user(self):
        """
        登录user页面
        :return:
        """
        self.send_keys((By.NAME, 'username'), 'root')
        self.send_keys((By.NAME, 'password'), 123456)
        self.click((By.NAME, 'submit'))

    def quit(self,seconds=3):
        sleep(seconds)
        return self.driver.quit()


if __name__ == '__main__':
    driver = get_driver()
    case = Base(driver)
    # case.get('https://www.baidu.com')
    # case.find_element((By.ID,'kw'))
    # # case.send_keys((By.ID,'kw'),'天气预报')
    # # case.click((By.ID,'su'))
    # print(case.text((By.LINK_TEXT, '新闻')))
    # case.quit()

    case.login_user()